#include "../include/Reconocedor.h"

void Reconocedor::cargar(vector<Matriz> fotos_p){
    //cargo las fotos
    for (uint i = 0; i < fotos_p.size(); i++){
        //recorro el vector de matrices
        vector<TFloat> foto;
        for (int j = 0; j < fotos_p[i].alto; j++)
            //recorro por filas
            for (int k = 0; k < fotos_p[i].ancho; k++){
                //recorro por columnas
                //paso al vector correspondiente a la foto
                TFloat t(precision);
                t = fotos_p[i][j][k];
                foto.push_back(t);
            }
        //agrego la foto a mi estructura
        fotos.push_back(foto);
    }
}

void Reconocedor::leer_dir(string dir){
	struct dirent *entry;
	vector<Matriz> matrices;
	DIR *pDIR = opendir(dir.c_str());
	if (pDIR == NULL){
        cerr << "Error abriendo un directorio" << endl;
    }
    while((entry = readdir(pDIR))){
        string nombre = entry->d_name;
        if (nombre.size() > 4 and nombre.compare(nombre.size() - 4, 4, ".new") == 0)
            fotos_nombres.push_back(entry->d_name);
    }
    closedir(pDIR);
    for (uint i = 0; i < fotos_nombres.size(); i++){
        Matriz m;
        string archivo_nombre;
        archivo_nombre = dir + "/" + fotos_nombres[i];
        ifstream archivo(archivo_nombre.c_str());
        m.cargar(archivo, precision);
        matrices.push_back(m);
    }
    cargar(matrices);
    cout << "Si no hubo errores hasta aquí, las fotos fueron cargadas correctamente." << endl;
}

void Reconocedor::calcular_promedio(){
    //calculo el promedio
    //hago la suma
    //inicializo el promedio
    for (uint i = 0; i < fotos[0].size(); i++){
        TFloat t(precision);
        t = fotos[0][i];
        promedio.push_back(t);
    }
    for (uint i = 1; i < fotos.size(); i++)
        //recorro las fotos. empiezo por la segunda porque hice que promedio se
        //copie de la 1ra foto (que seguro existe porque el vector es no vacío)
        for (uint j = 0; j < promedio.size(); j++){
            //recorro las componentes de las fotos
            promedio[j] = promedio[j] + fotos[i][j];
        }
    //divido por la cantidad de fotos
    for (uint i = 0; i < promedio.size(); i++){
        promedio[i] = promedio[i] / (double) fotos.size();
    }
}

void Reconocedor::calcular_covarianza(){
    //inicializo la matriz de covarianza
    int n = fotos.size();
    int m = fotos[0].size();
    covarianza = Matriz(m, m, precision);
    //calculo el divisor
    TFloat divisor(precision);
    divisor = 1.0 / ((double) n - 1.0);
    //hago la sumatoria
    for (int i = 0; i < n; i++){
        Matriz v1(fotos[i]);
        v1 = v1.restar(promedio);
        Matriz v2 = v1.trasponer();
        Matriz r = v1.multiplicar(v2);
        covarianza = covarianza.sumar(r);
        cout << "Voy por la foto " << i << endl;
    }
    //multiplico por el divisor
    covarianza = covarianza.multiplicar(divisor);
}

void Reconocedor::calcular_autovectores(){
    TFloat tol = 0.001;
    int max_it = 100;
    autovectores = covarianza.autovectores(tol, max_it);
}

void Reconocedor::entrenar(){
    cout << "Calculando el promedio." << endl;
    calcular_promedio();
    cout << "Calculando la matriz de covarianza." << endl;
    calcular_covarianza();
    cout << "Calculando autovectores." << endl;
    calcular_autovectores();
}

